<script setup lang="ts">
import { Delete, Plus } from '@element-plus/icons-vue';
import { modelThingService } from '@great/services';
import { DynamicSelect } from '@great/components';
import { useRequest } from 'vue-request';
import { ElMessage } from 'element-plus';

const model = defineModel<any[]>({ default: [] });

const fieldType = defineModel<string>('fieldType');
const attributeListMap = new Map<string, any[]>();

const { data } = useRequest(async () => {
    const res = await modelThingService.getPageTree({
        current: 1,
        size: -1,
        usageType: 'BUSINESS'
    });

    function loop(list) {
        const result: any[] = [];
        list.forEach(item => {
            const newItem = {
                label: item.displayName,
                value: item.objectName
            };
            if (item.children && item.children.length > 0) {
                newItem['children'] = loop(item.children);
            }
            result.push(newItem);
        });
        return result;
    }
    return loop(res.data?.records);
});

async function getOptions(objectName: string, showAll?: boolean) {
    if (objectName) {
        const res = await modelThingService.attribute.getList({
            current: 1,
            size: -1,
            objectName
        });
        const list = res.data?.records || [];
        attributeListMap.set(objectName, list);
        return list
            .filter(item => {
                return !!showAll || item.attributeName === 'id' || item.createIndex;
            })
            .map(item => ({
                label: item.displayName,
                value: item.attributeName
            }));
    }
    return [];
}
function onAddItem() {
    model.value = [...model.value, { objectName: '', attributeName: '' }];
}

function onRemoveItem(index: number) {
    model.value.splice(index, 1);
    if (model.value.length === 0) {
        fieldType.value = undefined;
    }
}

function onAttributeNameChange(val: string, item: any) {
    let value = fieldType.value;
    if (model.value.filter(item => item.attributeName).length === 1) {
        value = undefined;
    }
    if (!value && item.typeName === 'Auto-Number') {
        value = 'bigint';
    } else if (val) {
        const attribute = attributeListMap.get(item.objectName)?.find(item => item.attributeName === val);
        const fieldType = item.typeName === 'Auto-Number' ? 'bigint' : attribute?.fieldType;
        if (attribute && value && fieldType !== value) {
            item.attributeName = '';
            ElMessage.error('所有关联对象属性的字段类型必须一致，请重新选择该属性');
        } else {
            value = fieldType;
        }
    } else if (model.value.every(item => !item.attributeName)) {
        value = undefined;
    }
    fieldType.value = value;
}
</script>

<template>
    <div class="related-object-field">
        <div class="item" v-for="(item, index) in model" :key="item">
            <el-tree-select v-model="item.objectName" :data="data" filterable placeholder="请选择对象" />
            <DynamicSelect
                v-model="item.attributeName"
                :fetch-options="getOptions"
                :reload-deps="[() => item.objectName]"
                placeholder="必选，请选择关联属性"
                @update:model-value="val => onAttributeNameChange(val, item)"
            />
            <DynamicSelect
                v-model="item.displayAttributeName"
                :fetch-options="getOptions"
                :reload-deps="[() => item.objectName, () => true]"
                placeholder="可选，请选择显示属性"
            />
            <el-button :icon="Delete" @click="onRemoveItem(index)" />
        </div>
        <div class="actions">
            <el-button :icon="Plus" @click="onAddItem" style="border-style: dashed">添加项</el-button>
        </div>
    </div>
</template>

<style scoped lang="scss">
.related-object-field {
    width: 100%;
}
.item {
    display: flex;
    gap: 8px;
    margin-bottom: 10px;
    .el-select {
        flex: 1;
        width: 0;
    }
    .el-button {
        width: 24px;
    }
}
.actions {
    .el-button {
        width: 100%;
    }
}
</style>
